package com.leenmvc.core.dao.mysql.wrapper;

import com.leenmvc.core.base.BaseEntity;
import com.leenmvc.core.dao.communal.Wrapper;
import com.leenmvc.core.dao.communal.WrapperFactory;
import com.leenmvc.core.enums.EntityInfoEnum;
import com.leenmvc.core.utils.thread.ThreadLocalManager;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;

import java.util.Map;
import java.util.concurrent.LinkedBlockingQueue;

/**
 * 这个类用来管理实际使用的wrapper类
 * 使用池技术， 固定Wrapper的数量以达到节约内存的作用
 */
public class MysqlWrapperFactory implements WrapperFactory {

    private final static Logger logger = LoggerFactory.getLogger(MysqlWrapperFactory.class);

    private static LinkedBlockingQueue<QueryWrapper> queryWrappers = new LinkedBlockingQueue<>();

    private static LinkedBlockingQueue<DeleteWrapper> deleteWrappers = new LinkedBlockingQueue();

    private static LinkedBlockingQueue<UpdateWrapper> updateWrappers = new LinkedBlockingQueue<>();

    private static LinkedBlockingQueue<CountWrapper> countWrappers = new LinkedBlockingQueue<>();

    static {
        for (int i = 0; i < 2000; i++) {
            queryWrappers.add(new QueryWrapper());
        }
        for (int i = 0; i < 1000; i++) {
            deleteWrappers.add(new DeleteWrapper());
            updateWrappers.add(new UpdateWrapper());
            countWrappers.add(new CountWrapper());
        }
    }

    /**
     * 获取可用的countWrapper
     *
     * @return
     */
    public <T> T getCountWrapper(Class<?> cls) {
        CountWrapper wrapper = null;
        try {
            wrapper = countWrappers.take();
        } catch (InterruptedException e) {
            e.printStackTrace();
        }
        ThreadLocalManager.addWrapper(wrapper);
        wrapper.setCls(cls);
        return (T) wrapper;
    }

    /**
     * 获取可用的wrapper
     *
     * @return
     */
    public <T> T getQueryWrapper(Class<?> cls) {
        QueryWrapper wrapper = null;
        try {
            logger.info("还有{}个queryWrapper", queryWrappers.size());
            wrapper = queryWrappers.take();

        } catch (InterruptedException e) {
            logger.error(e.getMessage(), e);
        }
        ThreadLocalManager.addWrapper(wrapper);
        wrapper.setCls(cls);
        wrapper.setOutColumns(BaseEntity.getFields(EntityInfoEnum.FILL_FIELD_COLUMN_LIST, cls));
        wrapper.setColumns(BaseEntity.getFields(EntityInfoEnum.COLUMNS, cls));
        wrapper.setFields(BaseEntity.getFields(EntityInfoEnum.FIELDS, cls));
        wrapper.setOneToMulFields(BaseEntity.getOneToMulDefaultQueryFields(cls));
        wrapper.setOneToOneFields(BaseEntity.getOneToOneDefaultQueryFields(cls));
        wrapper.setOutFields(BaseEntity.getFillFieldDefaultQueryFields(cls));
        wrapper.setOneFieldInFields(BaseEntity.getFieldInDefaultQueryFields(cls));
        return (T) wrapper;
    }

    public <T> T getQueryWrapper(Class<?> cls, Map<String, Object> params) {
        QueryWrapper wrapper = null;
        try {
            logger.info("还有{}个queryWrapper", queryWrappers.size());
            wrapper = queryWrappers.take();
        } catch (InterruptedException e) {
            logger.error(e.getMessage(), e);
        }
        ThreadLocalManager.addWrapper(wrapper);
        wrapper.setCls(cls);
        wrapper.setOutColumns(BaseEntity.getFields(EntityInfoEnum.FILL_FIELD_COLUMN_LIST, cls));
        wrapper.setColumns(BaseEntity.getFields(EntityInfoEnum.COLUMNS, cls));
        wrapper.setFields(BaseEntity.getFields(EntityInfoEnum.FIELDS, cls));
        wrapper.setOneToMulFields(BaseEntity.getOneToMulDefaultQueryFields(cls));
        wrapper.setOneToOneFields(BaseEntity.getOneToOneDefaultQueryFields(cls));
        wrapper.setOutFields(BaseEntity.getFillFieldDefaultQueryFields(cls));
        wrapper.setOneFieldInFields(BaseEntity.getFieldInDefaultQueryFields(cls));
        wrapper.mapToWrapper(params);
        return (T) wrapper;
    }

    /**
     * 获取可用的wrapper
     *
     * @return
     */
    public <T, K> T getUpdateWrapper(K t) {
        UpdateWrapper wrapper = null;
        try {
            wrapper = updateWrappers.take();
        } catch (InterruptedException e) {
            logger.error(e.getMessage(), e);
        }
        ThreadLocalManager.addWrapper(wrapper);
        wrapper.update(t);
        return (T) wrapper;
    }

    /**
     * 获取可用的wrapper
     *
     * @return
     */
    public <T> T getUpdateWrapper(Class<?> cls) {
        UpdateWrapper wrapper = null;
        try {
            wrapper = updateWrappers.take();
        } catch (InterruptedException e) {
            logger.error(e.getMessage(), e);
        }
        ThreadLocalManager.addWrapper(wrapper);
        wrapper.setCls(cls);
        return (T) wrapper;
    }

    /**
     * 获取可用的wrapper
     *
     * @return
     */
    public <T> T getUpdateWrapper(Class<?> cls, Map<String, Object> params) {
        UpdateWrapper wrapper = null;
        try {
            wrapper = updateWrappers.take();
        } catch (InterruptedException e) {
            logger.error(e.getMessage(), e);
        }
        ThreadLocalManager.addWrapper(wrapper);
        wrapper.update(cls, params);
        return (T) wrapper;
    }

    /**
     * 获取可用的wrapper
     *
     * @return
     */
    public <T> T getDeleteWrapper(Class<?> cls) {
        DeleteWrapper wrapper = null;
        try {
            wrapper = deleteWrappers.take();
        } catch (InterruptedException e) {
            logger.error(e.getMessage(), e);
        }
        ThreadLocalManager.addWrapper(wrapper);
        wrapper.setCls(cls);
        return (T) wrapper;
    }

    /**
     * 关闭wrapper
     *
     * @param wrapper
     */
    public void closeWrapper(Wrapper wrapper) {
        closeWrapper(wrapper, false);
        ThreadLocalManager.removeWrapper(wrapper);
    }

    /**
     * ThreadLocalManager专用
     *
     * @param wrapper
     */
    public void closeWrapper(Wrapper wrapper, boolean threadLocalM) {
        if (wrapper instanceof QueryWrapper) closeWrapper((QueryWrapper) wrapper);
        if (wrapper instanceof UpdateWrapper) closeWrapper((UpdateWrapper) wrapper);
        if (wrapper instanceof DeleteWrapper) closeWrapper((DeleteWrapper) wrapper);
        if (wrapper instanceof CountWrapper) closeWrapper((CountWrapper) wrapper);
    }

    /**
     * 关闭在用的wrapper
     *
     * @param wrapper
     */
    private static void closeWrapper(QueryWrapper wrapper) {
        wrapper.clear();
        queryWrappers.add(wrapper);
    }

    /*
     * 关闭在用的wrapper
     *
     * @param wrapper
     */
    private static void closeWrapper(UpdateWrapper wrapper) {
        wrapper.clear();
        updateWrappers.add(wrapper);
    }

    /*
     * 关闭在用的wrapper
     *
     * @param wrapper
     */
    private static void closeWrapper(DeleteWrapper wrapper) {
        wrapper.clear();
        deleteWrappers.add(wrapper);
    }

    /*
     * 关闭在用的wrapper
     *
     * @param wrapper
     */
    private static void closeWrapper(CountWrapper wrapper) {
        wrapper.clear();
        countWrappers.add(wrapper);
    }

}
